package com.piece.admin.context;

import com.alibaba.fastjson.JSON;
import com.piece.admin.context.socket.WebSocketEvent;
import com.piece.core.log.support.socket.SocketLog;
import com.piece.core.framework.support.serializer.FastJsonSerializer;
import lombok.Data;
import org.apache.commons.lang3.time.DateFormatUtils;
import javax.websocket.Session;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

/**
 * WebSocket通讯上下文域
 */
public class LogContext extends HashMap<String, Object> {

    private String id = UUID.randomUUID().toString().replace("-", "");

    private Session session;

    private boolean debug;

    private volatile boolean running = true;

    private Object lock = new Object();

    public LogContext(Session session) {
        this.session = session;
    }

    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    public boolean isRunning() {
        return running;
    }

    public void setRunning(boolean running) {
        this.running = running;
    }

    public void addOutput(SocketLog auditLog) {
        this.start(new WebSocketEvent<>("output", auditLog));
    }

    public void addLog(SocketLog log) {
        this.start(new WebSocketEvent<>("log", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"), log));
    }

    public <T> void start(WebSocketEvent<T> event) {
        try {
            String message = JSON.toJSONString(event, FastJsonSerializer.serializeConfig);
            if (session.isOpen()) {
                synchronized (session) {
                    session.getBasicRemote().sendText(message);
                }
            }
        } catch (Throwable ignored) {
        }
    }

    public void pause(String nodeId, String event, String key, Object value) {
        if (this.debug && this.isRunning()) {
            synchronized (this) {
                if (this.debug && this.isRunning()) {
                    synchronized (lock) {
                        try {
                            this.start(new WebSocketEvent<>("debug", new DebugInfo(nodeId, event, key, value)));
                            lock.wait();
                        } catch (InterruptedException ignored) {
                        }
                    }
                }
            }
        }
    }

    public void resume() {
        if (this.debug) {
            synchronized (lock) {
                lock.notify();
            }
        }
    }

    public void stop() {
        if (this.debug) {
            synchronized (lock) {
                lock.notifyAll();
            }
        }
    }

    @Data
    class DebugInfo {
        private String nodeId;
        private String event;
        private String key;
        private Object value;

        public DebugInfo(String nodeId, String event, String key, Object value) {
            this.nodeId = nodeId;
            this.event = event;
            this.key = key;
            this.value = value;
        }
    }
}
